home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 134 (1991-10)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 134 (1991-10)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / GIFMachine / Sources / main.c < prev    next >
C/C++ Source or Header  |  1991-09-01  |  11KB  |  512 lines

  1. /* Copyright 1990 by Christopher A. Wichura.
  2.    See file GIFMachine.doc for full description of rights.
  3. */
  4.  
  5. #include "GIFMachine.h"
  6. #include <dos/rdargs.h>
  7. #include <dos/dosasl.h>
  8. #include <dos/stdio.h>
  9. #include <workbench/startup.h>
  10.  
  11. struct GIFdescriptor gdesc;
  12.  
  13. struct RGB **BitPlane;
  14. struct RGB GlobalColourTable[256];
  15.  
  16. extern UWORD *SHAMmem;
  17.  
  18. extern BYTE *PlaneBuf;
  19.  
  20. extern BOOL Laced;
  21.  
  22. extern UBYTE *Planes[24];
  23.  
  24. ULONG ImageNumber;
  25.  
  26. extern struct MinList CommentList;
  27.  
  28. /* indicates which memory list to allocate from */
  29. extern UWORD CurrentMem;
  30.  
  31. /* the current GIF file handle */
  32. BPTR GIFfh = NULL;
  33.  
  34. /* flag: display line counts during conversion or not */
  35. BOOL DisplayCounts;
  36.  
  37. /* here we have some defines relating to our GADS call */
  38. #define ESC "\x1B["
  39. #define GIFMACH ESC "1;33;42mGIFMachine" ESC "0;32;40m"
  40.  
  41. #define ARG_TEMPLATE "GIFfiles/A/M,TO/K,ALL/S,NOBORDER/N/K,XCOMP/S,DITHER/S,XFLIP/S,YFLIP/S,DEEP/S,NOCOUNT/S,BUFSIZE/N/K"
  42. enum ReadArgs {
  43.     ARG_FILES,
  44.     ARG_TO,
  45.     ARG_ALL,
  46.     ARG_NOBORD,
  47.     ARG_XCOMP,
  48.     ARG_DITHER,
  49.     ARG_FLIPX,
  50.     ARG_FLIPY,
  51.     ARG_DEEP,
  52.     ARG_NOCOUNT,
  53.     ARG_BUFSIZ,
  54.     ARG_sizeof
  55. };
  56.  
  57. /* we will make the argument array global so that other modules can get at
  58.    the ARG_TO, ARG_ALL and ARG_XCOMP fields easily */
  59. struct RDArgs *ArgsPtr;
  60. char *ArgArray[ARG_sizeof];
  61. BOOL ArgToIsDir;
  62.  
  63. /* size of the read buffered i/o space */
  64. static ULONG BufSize = 2048;    /* default size is 2k */
  65.  
  66. int NoBorderLineThresh = 0;
  67.  
  68. /* some mem pointers used when we do dithering */
  69. BYTE *CurrentLineErr[3];
  70. BYTE *LastLineErr[3];
  71.  
  72. /* this flag says if we scaled the image */
  73. BOOL DidXComp;
  74.  
  75. /* we print this when the user hits the break key */
  76. char *AbortMsg = "*** User Interruption!\n";
  77.  
  78. /* storage for our library bases */
  79. struct Library *MathIeeeDoubBasBase = NULL;
  80. struct Library *IFFParseBase = NULL;
  81. struct Library *GfxBase = NULL;
  82.  
  83. /* storage for our anchor when looking for pattern matches */
  84. struct Anchor {
  85.         struct AnchorPath APath;
  86.         char              Path[256];
  87.     } *anchor = NULL;
  88.  
  89. /* here we have our main routine */
  90. int __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg)
  91. {
  92.     register char **FilesPtr;
  93.     struct RDArgs MyArgs;
  94.     extern UBYTE __far arg_help[];
  95.     extern UBYTE __far VersionID[];
  96.  
  97.     InitMemory();
  98.  
  99.     if (WBMsg) {
  100.         WarnMustUseCLI();
  101.         MyExit(5);
  102.     }
  103.  
  104.     if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37))) {
  105.         MyPrintf("Unable to access %s!\n", "graphics.library");
  106.         MyExit(5);
  107.     }
  108.  
  109.     if (!(MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library", 0))) {
  110.         MyPrintf("Unable to access %s!\n", "mathieeedoubbas.library");
  111.         MyExit(5);
  112.     }
  113.  
  114.     if (!(IFFParseBase = OpenLibrary("iffparse.library", 0))) {
  115.         MyPrintf("Unable to access %s!\n", "iffparse.library");
  116.         MyExit(5);
  117.     }
  118.  
  119.     memset ((char *)&MyArgs, 0, sizeof(struct RDArgs));
  120.  
  121.     if (!(MyArgs.RDA_ExtHelp = (UBYTE *)MyAlloc(strlen(arg_help) + (2 * strlen(GIFMACH)) + strlen(VersionID) + 1))) {
  122.         PutStr("Out of memory!\n");
  123.         MyExit(5);
  124.     }
  125.  
  126.     MySPrintf((char *)MyArgs.RDA_ExtHelp, arg_help, GIFMACH, VersionID, GIFMACH);
  127.  
  128.     if (!(ArgsPtr = ReadArgs(ARG_TEMPLATE, (LONG *)&ArgArray, &MyArgs))) {
  129.         PrintFault(IoErr(), NULL);
  130.         MyExit(5);
  131.     }
  132.  
  133.     MyFree((char *)MyArgs.RDA_ExtHelp);
  134.  
  135.     if (ArgArray[ARG_TO])
  136.         ArgToIsDir = IsDir(ArgArray[ARG_TO]);
  137.  
  138.     if (ArgArray[ARG_NOBORD]) {
  139.         NoBorderLineThresh = *((LONG *)ArgArray[ARG_NOBORD]);
  140.         if (NoBorderLineThresh < 0 || NoBorderLineThresh > 100) {
  141.             PutStr("Invalid NOBORDER line threshhold specified.\n");
  142.             MyExit(3);
  143.         }
  144.     }
  145.  
  146.     if (ArgArray[ARG_NOCOUNT])
  147.         DisplayCounts = FALSE;
  148.     else
  149.         DisplayCounts = TRUE;
  150.         
  151.     if (ArgArray[ARG_BUFSIZ])
  152.         BufSize = *((LONG *)ArgArray[ARG_BUFSIZ]) * 1024;
  153.  
  154.     if (!(FilesPtr = (char **)ArgArray[ARG_FILES])) {
  155.         PutStr("No GIF files selected.\n");
  156.         MyExit(3);
  157.     }
  158.  
  159.     InitDiff();    /* one time init for the RGBdiff function */
  160.  
  161.     while (*FilesPtr)
  162.         DoPattern(*FilesPtr++);
  163.  
  164.     MyExit(0);
  165. }
  166.  
  167. void MyExit(ULONG result)
  168. {
  169.     if (GIFfh)
  170.         Close(GIFfh);
  171.  
  172.     if (IFFParseBase)
  173.         CloseLibrary(IFFParseBase);
  174.  
  175.     if (MathIeeeDoubBasBase)
  176.         CloseLibrary(MathIeeeDoubBasBase);
  177.  
  178.     if (GfxBase)
  179.         CloseLibrary(GfxBase);
  180.  
  181.     if (anchor)
  182.         MatchEnd(&anchor->APath);
  183.  
  184.     if (ArgsPtr)
  185.         FreeArgs(ArgsPtr);
  186.  
  187.     FreeAll(1);
  188.     FreeAll(0);
  189.  
  190.     XCEXIT(result);
  191. }
  192.  
  193.  
  194. /* this will walk through a pattern doing conversions */
  195. void DoPattern(char *pat)
  196. {
  197.     register int error;
  198.  
  199.     if (!(anchor = (struct Anchor *)MyAlloc(sizeof(struct Anchor)))) {
  200.         PutStr("Out of memory!\n");
  201.         MyExit(10);
  202.     }
  203.  
  204.     anchor->APath.ap_Strlen = sizeof(anchor->Path);
  205.     anchor->APath.ap_Flags = APF_DOWILD;
  206.     anchor->APath.ap_BreakBits = SIGBREAKF_CTRL_C;
  207.  
  208.     error = MatchFirst(pat, &anchor->APath);
  209.  
  210.     while (!error) {
  211.         if (anchor->APath.ap_Info.fib_DirEntryType > 0) {
  212.             if (ArgArray[ARG_ALL]) {
  213.                 if (!(anchor->APath.ap_Flags & APF_DIDDIR))
  214.                     anchor->APath.ap_Flags |= APF_DODIR;
  215.                 anchor->APath.ap_Flags &= ~APF_DIDDIR;
  216.             }
  217.         } else
  218.             Convert(anchor->APath.ap_Buf);
  219.  
  220.         error = MatchNext(&anchor->APath);
  221.     }
  222.  
  223.     MatchEnd(&anchor->APath);
  224.     MyFree((char *)anchor);
  225.     anchor = NULL;
  226.  
  227.     switch(error) {
  228.         case ERROR_BREAK:
  229.             PutStr(AbortMsg);
  230.             MyExit(ABORTEXITVAL);
  231.             break;
  232.  
  233.         case ERROR_OBJECT_NOT_FOUND:
  234.             PutStr("File not found.\n");
  235.             break;
  236.  
  237.         case ERROR_BUFFER_OVERFLOW:
  238.             PutStr("Path too long!\n");
  239.             break;
  240.  
  241.         case ERROR_NO_MORE_ENTRIES:    /* normal termination */
  242.             break;
  243.  
  244.         default:
  245.             MyPrintf("I/O Error #%ld!\n", error);
  246.             break;
  247.     }
  248. }
  249.  
  250. /* here we have the routine that gets ready to do the conversion */
  251. void Convert(char *name)
  252. {
  253.     register int index;
  254.     char *basename;
  255.     char *ptr;
  256.     char sig[7];
  257.     int size;
  258.     int error;
  259.     int colours;
  260.     LONG cmdcode;
  261.     
  262.     struct DateStamp StartTime, EndTime;
  263.  
  264.     CurrentMem++;
  265.  
  266.     if (!(GIFfh = Open(name, MODE_OLDFILE))) {
  267.         MyPrintf("Error #%ld trying to open %s...\n", IoErr(), name);
  268.         goto LeaveConvert;
  269.     }
  270.  
  271.     SetVBuf(GIFfh, NULL, BUF_FULL, BufSize);
  272.  
  273.     sig[6] = NULL;
  274.  
  275.     if (FRead(GIFfh, sig, 1, 6) != 6 || strncmp("GIF", sig, 3)) {
  276.         MyPrintf("%s is not a GIF file...\n", name);
  277.         goto LeaveConvert;
  278.     }
  279.  
  280.     MyPrintf("Converting %s ", name);
  281.  
  282.     basename = FilePart(name);
  283.     ptr = basename + strlen(basename) - 4;
  284.  
  285.     if (!strnicmp(".gif", ptr, 4))
  286.         *ptr = NULL;
  287.  
  288.     size = strlen(basename) + 6;
  289.  
  290.     if (ArgArray[ARG_TO]) {
  291.         if (ArgToIsDir)
  292.             size += strlen(ArgArray[ARG_TO]) + 1;
  293.         else
  294.             size = strlen(ArgArray[ARG_TO]) + 1;
  295.     }
  296.  
  297.     if (!(ptr = MyAlloc(size))) {
  298.         PutStr("... Out of memory!\n");
  299.         goto LeaveConvert;
  300.     }
  301.  
  302.     if (ArgArray[ARG_TO]) {
  303.         strcpy(ptr, ArgArray[ARG_TO]);
  304.  
  305.         if (ArgToIsDir) {
  306.             AddPart(ptr, basename, size);
  307.             strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
  308.         }
  309.     } else {
  310.         strcpy(ptr, basename);
  311.         strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
  312.     }
  313.  
  314.     MyPrintf("to %s...\n", ptr);
  315.  
  316.     DateStamp(&StartTime);
  317.  
  318.     if (FRead(GIFfh, (char *)&gdesc, 1, 7) != 7) {
  319.         PutStr("Error reading screen descriptor.\n");
  320.         goto LeaveConvert;
  321.     }
  322.  
  323.     FlipWord(&gdesc.gd_Width);
  324.     FlipWord(&gdesc.gd_Height);
  325.  
  326.     MyPrintf("Signature = \"%s\", Width = %ld, Height = %ld\n",
  327.         sig, gdesc.gd_Width, gdesc.gd_Height);
  328.  
  329.     NewList((struct List *)&CommentList);
  330.  
  331.     DidXComp = 0;
  332.     colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
  333.  
  334.     if (!(gdesc.gd_ColInfo & 1L << 7)) {
  335.         PutStr("No global colour map supplied, using internal.\n");
  336.  
  337.         for (index = 0; index < colours; index++) {
  338.             GlobalColourTable[index].rgb_Red   =
  339.             GlobalColourTable[index].rgb_Green =
  340.             GlobalColourTable[index].rgb_Blue  = index;
  341.         }
  342.     } else {
  343.         MyPrintf("Global colour map contains %ld entries.\n", colours);
  344.  
  345.         for (index = 0; index < colours; index++) {
  346.             if (FRead(GIFfh, &GlobalColourTable[index], 1, 3) != 3) {
  347.                 MyPrintf("Error reading global colour #%ld.\n",
  348.                     index);
  349.                 goto LeaveConvert;
  350.             }
  351.         }
  352.     }
  353.  
  354.     size = ((gdesc.gd_Width + 7) / 8) + 1;
  355.     size += (size + 127) >> 7;
  356.  
  357.     if (!(BitPlane = (struct RGB **)MyAlloc(gdesc.gd_Height * sizeof(struct RGB *))) ||
  358.         !(SHAMmem  = (UWORD *)MyAlloc(gdesc.gd_Height * 16 * sizeof(UWORD))) ||
  359.         !(PlaneBuf = (BYTE *)MyAlloc(size))) {
  360.         PutStr("Out of memory trying to allocate picture.\n");
  361.         goto LeaveConvert;
  362.     }
  363.  
  364.     size = (gdesc.gd_Width + 1) * sizeof(struct RGB);
  365.  
  366.     for (index = 0; index < gdesc.gd_Height; index++)
  367.         if (!(BitPlane[index] = (struct RGB *)MyAlloc(size))) {
  368.             PutStr("Out of memory trying to allocate picture.\n");
  369.             goto LeaveConvert;
  370.         }
  371.  
  372.     size = ((gdesc.gd_Width + 7) / 8) + 1;
  373.     for (index = 0; index < (ArgArray[ARG_DEEP] ? 24 : 6); index++)
  374.         if (!(Planes[index] = (UBYTE *)MyAlloc(size))) {
  375.             PutStr("Out of memory trying to allocate picture.\n");
  376.             goto LeaveConvert;
  377.         }
  378.  
  379.     if (ArgArray[ARG_DITHER]) {
  380.         size = gdesc.gd_Width * sizeof(BYTE);
  381.  
  382.         for (index = 0; index < 3; index++)
  383.             if (!(CurrentLineErr[index] = (BYTE *)MyAlloc(size)) ||
  384.                 !(LastLineErr[index] = (BYTE *)MyAlloc(size))) {
  385.                 PutStr("Out of memory trying to allocate picture.\n");
  386.                 goto LeaveConvert;
  387.             }
  388.     }
  389.  
  390.     ImageNumber = 1;
  391.  
  392.     /* at this point we start looking for images, extensions or the gif
  393.        terminator.  we call the appropriate routine as we find each. */
  394.  
  395.     for (error = FALSE; error == FALSE;) {
  396.         if ((cmdcode = FGetC(GIFfh)) == -1) {
  397.             PutStr("...I/O error reading GIF file.\n");
  398.             goto LeaveConvert;
  399.         }
  400.  
  401.         switch(cmdcode) {
  402.             case GIF_IMAGE:
  403.                 error = DoImage(GIFfh);
  404.                 break;
  405.  
  406.             case GIF_EXTENSION:
  407.                 error = DoExtension(GIFfh);
  408.                 break;
  409.  
  410.             case GIF_TERMINATOR:
  411.                 if (ArgArray[ARG_NOBORD])
  412.                     StripBorder();
  413.  
  414.                 if (ArgArray[ARG_FLIPX])
  415.                     DoXFlip();
  416.  
  417.                 if (ArgArray[ARG_FLIPY])
  418.                     DoYFlip();
  419.  
  420.                 if (ArgArray[ARG_XCOMP]) {
  421.                     DoXComp();
  422.                     DidXComp = 1;
  423.                 }
  424.  
  425.                 if (gdesc.gd_Height > 200 && DidXComp)
  426.                     Laced = TRUE;
  427.                 else
  428.                     Laced = FALSE;
  429.  
  430.                 if (!ArgArray[ARG_DEEP]) {
  431.                     if (ArgArray[ARG_DITHER])
  432.                         DitherTo12();
  433.                     else
  434.                         ReduceTo12();
  435.  
  436.                     GIFtoSHAM();
  437.                 }
  438.  
  439.                 error = WriteIFF(ptr, (BOOL)ArgArray[ARG_DEEP]);
  440.                 break;
  441.  
  442.             default:
  443.                 MyPrintf("...Unknown directive #%ld encountered.\n",
  444.                     cmdcode);
  445.                 error = TRUE;
  446.         }
  447.     }
  448.  
  449.     DateStamp(&EndTime);
  450.  
  451.     {
  452.         register ULONG Hours;
  453.         register ULONG Minutes;
  454.         register ULONG Seconds;
  455.         register ULONG Seconds2;
  456.     
  457.         Seconds = (EndTime.ds_Days * 86400) + (EndTime.ds_Minute * 60) + (EndTime.ds_Tick / TICKS_PER_SECOND);
  458.         Seconds2 = (StartTime.ds_Days * 86400) + (StartTime.ds_Minute * 60) + (StartTime.ds_Tick / TICKS_PER_SECOND);
  459.  
  460.         Seconds -= Seconds2;
  461.  
  462.         Hours = Seconds / 3600;
  463.         Seconds -= Hours * 3600;
  464.  
  465.         Minutes = Seconds / 60;
  466.         Seconds -= Minutes * 60;
  467.  
  468.         MyPrintf("...Conversion time was %ld hour%s, %ld minute%s and %ld second%s.\n",
  469.             Hours, (Hours != 1 ? "s" : ""),
  470.             Minutes, (Minutes != 1 ? "s" : ""),
  471.             Seconds, (Seconds != 1 ? "s" : ""));
  472.     }
  473.  
  474. LeaveConvert:
  475.     FreeAll(CurrentMem--);
  476.  
  477.     if (GIFfh) {
  478.         Close(GIFfh);
  479.         GIFfh = NULL;
  480.     }
  481. }
  482.  
  483. /* this will check to see if we have a directory or not */
  484. BOOL IsDir(char *name)
  485. {
  486.     register BPTR lock;
  487.     register BOOL result = FALSE;
  488.  
  489.     struct FileInfoBlock __aligned fib;
  490.  
  491.     if (lock = Lock(name, ACCESS_READ)) {
  492.         if (Examine(lock, &fib)) {
  493.             if (fib.fib_DirEntryType > 0)
  494.                 result = TRUE;
  495.         }
  496.         UnLock(lock);
  497.     }
  498.  
  499.     return result;
  500. }
  501.  
  502. /* this will convert a word from LSB/MSB to MSB/LSB */
  503. void FlipWord(UWORD *word)
  504. {
  505.     register UBYTE swap1;
  506.     register UBYTE swap2;
  507.  
  508.     swap1 = *word & 0xFF;
  509.     swap2 = (*word & 0xFF00) >> 8;
  510.     *word = swap1 << 8 | swap2;
  511. }
  512.